package isssr.bean.utility;


import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;

import isssr.bean.entity.OrganizationalGoal;
import isssr.bean.entity.User;

import javax.management.relation.Role;

import org.hibernate.Hibernate;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;




public class StorageUtility {
	
	private static final SessionFactory sessionFactory = buildSessionFactory();
			
	private static SessionFactory buildSessionFactory() {
		if(StorageUtility.sessionFactory!=null) 
			return StorageUtility.sessionFactory;
		
        try {
        	Configuration cfg =new Configuration();
        	cfg.addAnnotatedClass(isssr.bean.entity.Role.class);
            // Create the SessionFactory from hibernate.cfg.xml
            return cfg.configure().buildSessionFactory();
        }
        catch (Throwable ex) {
            // Make sure you log the exception, as it might be swallowed
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }
	

	public static ArrayList<User> getEligibleSupers(User user, int firstResult, int pageSize)
	{
		Session session=null;
		
		String levelLabel = "Level";
		
		Query query;
		
		Iterator<User> eligibleSupers;
		ArrayList<User> result = new ArrayList<User>();
		
		try
		{ 
			 session = StorageUtility.sessionFactory.openSession();
			 Transaction tx = session.beginTransaction();
			 
			 query = session.createQuery( 	"select u from User as u inner join u.role as r " +
					 						"with r.Level >= :" + levelLabel
					 						)
	          .setParameter(levelLabel, user.getRole().getLevel());
			 
			 if(firstResult > 0)
			 {
				 query = query.setFirstResult(firstResult);
			 }
			 if(pageSize > 0)
			 {
				 query = query.setFetchSize(pageSize);
			 }
			 
			 eligibleSupers = (Iterator<User>)query.iterate();
			 
			 tx.commit();
	   
			 while(eligibleSupers.hasNext())
			 {
				 result.add(eligibleSupers.next());
			 }
			 
		}catch(Exception e){
			 e.printStackTrace();
		}
		 
		finally{
	   
			 session.close();
		}
		return result;
	}
	
	@SuppressWarnings("unchecked")
	public static ArrayList<User> getEligibleSupers(User user)
	{
		return getEligibleSupers(user, 0, 0);
	}
	

	public static ArrayList<User> getEligibleEnactors(User user, int firstResult, int pageSize)
	{
		Session session=null;
		
		String levelLabel = "Level";
		
		Iterator<User> eligibleEnactors;
		ArrayList<User> result = new ArrayList<User>();
		
		try
		{ 
		     Query query;
			 session = StorageUtility.sessionFactory.openSession();
			 Transaction tx = session.beginTransaction();
			 
			 query = session.createQuery( 	"select u from User as u "
					  	+ "inner join u.role as r " 
					 	+ "with r.Level < :" + levelLabel 
						)
						.setParameter(levelLabel, user.getRole().getLevel())
						;

				System.out.println("queryString: " + query.getQueryString());
				System.out.println("User level: " + user.getRole().getLevel());
			 
			 if(firstResult > 0)
			 {
				 query = query.setFirstResult(firstResult);
			 }
			 if(pageSize > 0)
			 {
				 query = query.setFetchSize(pageSize);
			 }
			 
			 eligibleEnactors = (Iterator<User>) query.iterate();

			 tx.commit();
	   
			 session.flush();
			 while(eligibleEnactors.hasNext())
			 {
				 System.out.println("yolo");
				 result.add(eligibleEnactors.next());
			 }
			 
		}catch(Exception e){
			 e.printStackTrace();
		}
		 
		finally{
	   
			 session.close();
		}
		return result;
	}
	

	public static ArrayList<User> getEligibleEnactors(User user)
	{
		return getEligibleEnactors(user, 0, 0);
	}
	
	public static User verifyUser(String username, String pass)
	{
		 Session session=null;
		 Iterator iter;
		 User u=null;
	  
		 try
		 { 
			 session = StorageUtility.sessionFactory.openSession();
			 Transaction tx = session.beginTransaction();
	   
			 iter = session.createQuery( 	"select u from User as u " +
					 						"where u.username =  ?"+
					 						"and u.password = ?"
	          )
	          .setString(0, username)
	          .setString(1, pass)
	          .iterate();

				System.out.println( " - Query pronta ed eseguita");
			 if(iter.hasNext()) 
				 u = (User) iter.next();
			 System.out.println( " - ha cercato user u -- " + u);
	   
			 System.out.println("[HibernateUtility::submitQuery()] Post-query");
	   
			 tx.commit();
				System.out.println( " - Commit");
	   
			 System.out.println("[HibernateUtility::submitQuery()] Sessione chiusa");
	   
		 }catch(Exception e){
			 e.printStackTrace();
				System.out.println( " - Eccezione");
		 }
		 
		 finally{
	   
			 session.close();
		 }

		 return u;
	}
	
	
	
	public static Object retrieve(Class<?> c, String s)
	{
		Session session=null;
		Object result = null;
		System.out.println("[HibernateUtility::retrieve()] Dentro retrieve()");
		
		try
		{	
			session = StorageUtility.sessionFactory.openSession();
			Transaction tx = session.beginTransaction();

			System.out.println("[HibernateUtility::retrieve()] Pre-load");
			result = session.get( c , s);
			System.out.println("[HibernateUtility::retrieve()] Post-load");
			
			tx.commit();
			
			System.out.println("[HibernateUtility::retrieve()] Sessione chiusa");
			
		
	}catch(Exception e){
		e.printStackTrace();
	}
		finally{
		
			session.close();
		}
		return result;
	}
	

	public static void delete(Object ob)
	{
		Session session=null;
		System.out.println("[HibernateUtility::delete()] Dentro delete()");
		
		try
		{	
			session = StorageUtility.sessionFactory.openSession();
			Transaction tx = session.beginTransaction();

			System.out.println("[HibernateUtility::retrieve()] Pre-delete");
			session.delete(ob);
			System.out.println("[HibernateUtility::retrieve()] Post-delete");
			
			tx.commit();
			
			System.out.println("[HibernateUtility::retrieve()] Sessione chiusa");
			
		
	}catch(Exception e){
		e.printStackTrace();
	}
		finally{
		
			session.close();
		}
	}
	

	public static Object retrieve(Class<?> c, Integer id)
	{
		Session session=null;
		Object result = null;
		System.out.println("[HibernateUtility::retrieve()] Dentro retrieve()");
		
		try
		{	
			session = StorageUtility.sessionFactory.openSession();
			Transaction tx = session.beginTransaction();

			System.out.println("[HibernateUtility::retrieve()] Pre-load");
			result = session.get( c , id);
			System.out.println("[HibernateUtility::retrieve()] Post-load");
			
			tx.commit();
			
			System.out.println("[HibernateUtility::retrieve()] Sessione chiusa");
			
			
		}catch(Exception e){
			e.printStackTrace();
		}
		finally{
		
			session.close();
		}
		return result;
	}
	
	
	public static void persist(Object u) throws Exception {
		Session session	= null;
		Transaction tx	= null;
		
		System.out.println("[HibernateUtility::persist()] Dentro persist()");
		
		try 
		{
			session = StorageUtility.sessionFactory.openSession();
			tx 		= session.beginTransaction();
			System.out.println("[HibernateUtility::persist()] Pre-save");
			session.save(u);
			System.out.println("[HibernateUtility::persist()] Post-save");
			tx.commit();
		}
		catch(Exception ex)
		{
			throw ex;
		}
			
		finally
		{
			System.out.println("[HibernateUtility::persist()] Sessione chiusa");			
			session.close();	
		}		
	}
	
	
	public static void update(Object ob)
	{
		Session session=null;
		System.out.println("[HibernateUtility::update()] Dentro update()");
		
		try
		{	
			session = StorageUtility.sessionFactory.openSession();
			Transaction tx = session.beginTransaction();
			
			System.out.println("[HibernateUtility::update()] Pre-merge");
			session.merge(ob);
			System.out.println("[HibernateUtility::update()] Post-merge");
			
			tx.commit();
			
			System.out.println("[HibernateUtility::update()] Sessione chiusa");
			
			
		}catch(Exception e){
			e.printStackTrace();
		}
		finally{
		
			session.close();
		}
	}
	
	public static Iterator<OrganizationalGoal> getGoalsByOwner(User owner, int firstResult, int pageSize)
	{

		Session session=null;
		System.out.println("[HibernateUtility::update()] Dentro update()");
		
		Iterator<OrganizationalGoal> it 	= null;
		List<OrganizationalGoal> results 	= new ArrayList<OrganizationalGoal>();
		
		try
		{	
			session = StorageUtility.sessionFactory.openSession();
			Transaction tx = session.beginTransaction();
			Query query;
			
			System.out.println("[HibernateUtility::update()] Pre-merge");
			query = session.createQuery("select o from OrganizationalGoal as o where o.goalOwner = ?")
									.setEntity(0, owner);
			
			if(firstResult>0)
			{
				query = query.setFirstResult(firstResult);
			}
			if(pageSize>0)
			{
				query = query.setFetchSize(pageSize);
			}
			
			it = (Iterator<OrganizationalGoal>)query.iterate();
			
			System.out.println("[HibernateUtility::update()] Post-merge");
			while(it.hasNext())
			{
				OrganizationalGoal goal = (OrganizationalGoal) it.next();
				results.add(goal);
			}
			
			tx.commit();
			
			System.out.println("[HibernateUtility::update()] Sessione chiusa");
			
		}catch(Exception e){
			e.printStackTrace();
		}
		finally{
		
			session.close();
		}
		
		it = results.iterator();
		return it;
	}
	
	public static Iterator<OrganizationalGoal> getGoalsByOwner(User owner)
	{
		return getGoalsByOwner(owner, 0, 0);
	}

}
